﻿using PlayNugetPackage.WPF;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Linq;
using System.Net.Sockets;
using System.Runtime.CompilerServices;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;

namespace WpfApp1
{
    internal class MainWindowViewModel : INotifyPropertyChanged
    {
        public MainWindowViewModel() {

            _Clients.CollectionChanged += (s,e) =>
            {
                if (_Clients.Count > 0)
                {
                    SelectItemClient = _Clients[0];
                }
            };
        }
        List<Model> sockets=new List<Model> ();
        public event PropertyChangedEventHandler? PropertyChanged;
        private void NotifyPropertyChanged([CallerMemberName] string? propertyName = "")
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
        }
        private string? _ServerMsg;
        public string? ServerMsg
        {
            get
            {
                return _ServerMsg;
            }

            set
            {
                if (value != _ServerMsg)
                {
                    _ServerMsg = value;
                    NotifyPropertyChanged();
                }
            }
        }

        private string? _ClientMsg1;
        public string? ClientMsg1
        {
            get
            {
                return _ClientMsg1;
            }

            set
            {
                if (value != _ClientMsg1)
                {
                    _ClientMsg1 = value;
                    NotifyPropertyChanged();
                }
            }
        }

        private string? _ClientMsg2;
        public string? ClientMsg2
        {
            get
            {
                return _ClientMsg2;
            }

            set
            {
                if (value != _ClientMsg2)
                {
                    _ClientMsg2 = value;
                    NotifyPropertyChanged();
                }
            }
        }

        private string? _ServerShow;
        public string? ServerShow
        {
            get
            {
                return _ServerShow;
            }

            set
            {
                if (value != _ServerShow)
                {
                    _ServerShow = value;
                    NotifyPropertyChanged();
                }
            }
        }

        private string? _ClientShow1;
        public string? ClientShow1
        {
            get
            {
                return _ClientShow1;
            }

            set
            {
                if (value != _ClientShow1)
                {
                    _ClientShow1 = value;
                    NotifyPropertyChanged();
                }
            }
        }

        private string? _ClientShow2;
        public string? ClientShow2
        {
            get
            {
                return _ClientShow2;
            }

            set
            {
                if (value != _ClientShow2)
                {
                    _ClientShow2 = value;
                    NotifyPropertyChanged();
                }
            }
        }

        private ObservableCollection<ComboboxItemModel> _Clients=new ObservableCollection<ComboboxItemModel>();
         public ObservableCollection<ComboboxItemModel> Clients
        {
            get
            {
                return this._Clients;
            }
            set
            {
                _Clients = value;
                NotifyPropertyChanged();
            }
        }

        private ComboboxItemModel? _SelectItemClient;
        public ComboboxItemModel? SelectItemClient
        {
            get
            {
                return this._SelectItemClient;
            }
            set { if (_SelectItemClient != value) { this._SelectItemClient = value; NotifyPropertyChanged(); } }
        }

        //PlayNugetPackage.WPF.DelegateCommand

        private PCommand? _OpenConnect;
        public PCommand? OpenConnect
        {
            get
            {
                if (_OpenConnect == null)
                {
                    _OpenConnect = new PCommand()
                    {
                        CommandAction = () =>
                    {
                        MessageBox.Show("请配置连接类型");
                    },
                        CommandActionPar = o =>
                        {
                            if(int.TryParse(o.ToString(),out int i))
                            {
                                PSocket pSocket = new PSocket();
                                switch (i)
                                {
                                    case 0:
                                        var temp = pSocket.Open(isClient: false);
                                        if (temp!=null)
                                        {
                                            temp.OnReceviceData += (s,o) =>
                                            {
                                                ServerShow += o + "\n";
                                            };
                                            temp.OnDisconnected += (client) =>
                                            {
                                                ServerShow += $"设备{client?.RemoteEndPoint}连接断开\n";
                                            };
                                            if (temp is P_Server server)
                                            {
                                                server.OnClinetConnected += (client) =>
                                                {
                                                    ServerShow += $"新设备连接{client.RemoteEndPoint}\n";
                                                    System.Windows.Application.Current.Dispatcher.Invoke(() =>
                                                    {
                                                        var item = new ComboboxItemModel() { ShowTxt = $"", Val = client };
                                                        Clients.Add(item);
                                                        item.ShowTxt = $"客户端{Clients.Count}";
                                                        var model = sockets.FirstOrDefault(m => m.PSocket?.GetSocket()?.LocalEndPoint?.ToString() == client.RemoteEndPoint?.ToString());
                                                        if(model != null)
                                                        {
                                                            model.Uid = item.Uid;
                                                        }
                                                    });
                                                };
                                            }
                                            ServerShow += $"服务开启成功{temp.GetSocket()?.LocalEndPoint}\n";
                                            sockets.Add(new Model(i, temp,""));
                                        }
                                        break;
                                    case 1:
                                        if (sockets.FirstOrDefault(m => m.Id == i) == null)
                                        {
                                            var model = pSocket.Open(isClient: true);
                                            if (model != null)
                                            {
                                                model.OnReceviceData += (s, o) =>
                                                {
                                                    ClientShow1 += o + "\n";
                                                };
                                                if(model is P_Client client)
                                                {
                                                    client.OnDisconnected += (o) =>
                                                    {
                                                        lock (sockets)
                                                        {
                                                            var socket = sockets.FirstOrDefault(m => m.Id == i);
                                                            if (socket != null)
                                                            {
                                                                sockets.Remove(socket);
                                                                ClientShow1 += $"服务端断开连接\n";
                                                            }
                                                        }
                                                           
                                                    };
                                                }
                                                sockets.Add(new Model(i, model,""));
                                            }
                                            
                                        }
                                        break;
                                    case 2:
                                        if (sockets.FirstOrDefault(m => m.Id == i) == null)
                                        {
                                            var model = pSocket.Open(isClient: true);
                                            if (model != null)
                                            {
                                                model.OnReceviceData += (s, o) =>
                                                {
                                                    ClientShow2 += o + "\n";
                                                };
                                                if (model is P_Client client)
                                                {
                                                    client.OnDisconnected += (o) =>
                                                    {
                                                        lock (sockets)
                                                        {
                                                            var socket = sockets.FirstOrDefault(m => m.Id == i);
                                                            if (socket != null)
                                                            {
                                                                sockets.RemoveAt(sockets.IndexOf(socket));
                                                                ClientShow2 += $"服务端断开连接\n";
                                                            }
                                                        }
                                                        
                                                    };
                                                }
                                                sockets.Add(new Model(i, model, ""));
                                            }
                                        }
                                        break;
                                    default:
                                        MessageBox.Show("请配置连接类型");
                                        break;
                                }
                            }
                        }
                    };
                }
                return _OpenConnect;
            }
        }

        PCommand? _CloseConnect;
        public PCommand? CloseConnect
        {
            get
            {
                if(_CloseConnect == null)
                {
                    _CloseConnect = new PCommand() { CommandActionPar = (o) =>
                    {
                        if (int.TryParse(o.ToString(), out int i))
                        {
                            lock(sockets)
                            {
                                var temp = sockets.FirstOrDefault(m => m.Id == i);
                                if (temp != null)
                                {
                                    temp.PSocket?.CloseConnected();
                                    sockets.Remove(temp);
                                    var client = Clients.FirstOrDefault(m => m.Uid == temp.Uid);
                                    if (client != null)
                                    {
                                        Clients.Remove(client);
                                    }
                                    if (client == SelectItemClient)
                                    {
                                        SelectItemClient = null;
                                    }
                                    if (temp.PSocket is P_Server)
                                    {
                                        Clients.Clear();
                                    }
                                    if (temp.PSocket?.CloseConnected() == true)
                                    {
                                        MessageBox.Show($"关闭成功");
                                    }
                                    else
                                    {
                                        MessageBox.Show($"关闭失败");
                                    }
                                }
                            }
                            
                        }
                    } };
                }
                return _CloseConnect;
            }
        }
        private PCommand? _SendMsg;
        public PCommand? SendMsg
        {
            get
            {
                if (_SendMsg == null)
                {
                    _SendMsg = new PCommand() {
                        CommandAction = () =>
                        {
                        },
                        CommandActionPar = (o) =>
                        {
                            if(o is TextBox box)
                            {
                                var temp = sockets.FirstOrDefault(m => m.Id.ToString() == box.Tag.ToString());
                                if (temp != null)
                                {
                                    if (temp.PSocket is P_Server server)
                                    {
                                        server.SendData(box.Text, SelectItemClient?.Val);
                                    }
                                    else
                                    {
                                        temp.PSocket?.SendData(box.Text);
                                    }
                                    
                                }
                            }
                        }
                    };
                }
                return _SendMsg;
            }
        }

        
    }


    public class PCommand : ICommand
    {
        public Action? CommandAction { get; set; }

        public Action<object>? CommandActionPar { get; set; }

        public Func<bool>? CanExecuteFunc { get; set; }

        public event EventHandler? CanExecuteChanged;

        //
        // 参数:
        //   parameter:
        public void Execute(object? parameter)
        {

            if (parameter == null)
            {
                CommandAction?.Invoke();
            }
            else
            {
                CommandActionPar?.Invoke(parameter);
            }
        }

        //
        // 参数:
        //   parameter:
        public bool CanExecute(object? parameter)
        {
            return CanExecuteFunc == null || CanExecuteFunc();
        }

    }


    public class ComboboxItemModel: ViewModelBase
    {
        private string _Uid = Guid.NewGuid().ToString();
        public string Uid
        {
            get
            {
                return _Uid;
            }
        }
        private string? _ShowTxt;
        public string? ShowTxt
        {
            get
            {
                return _ShowTxt;
            }

            set
            {
                if (value != _ShowTxt)
                {
                    _ShowTxt = value;
                    OnPropertyChanged();
                }
            }
        }

        private Socket? _Val;
        public Socket? Val
        {
            get
            {
                return _Val;
            }
            set
            {
                if (value != _Val)
                {
                    _Val = value;
                    OnPropertyChanged();
                }
            }
        }

        public IPSocket? PSocket { get; set; }
        public bool IsServer
        {
            get
            {
                if (PSocket != null)
                {
                    return PSocket is P_Server;
                }
                return false;
            }
        }
    }

    public class Model
    {
        public Model()
        {

        }
        public Model(int id, IPSocket pSocket,string uid)
        {
            Id = id;
            Uid = uid;
            PSocket= pSocket;
        }
        public int Id { get; set; }
        public IPSocket? PSocket { get; set; }
        public string Uid { get; set; }=string.Empty;
    }

    //public class ViewModelBase:INotifyPropertyChanged
    //{

    //}
}
